home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / winsock / twnsck12.zip / SRC\TWINSOCK.C < prev    next >
Text File  |  1994-12-04  |  12KB  |  592 lines

  1. /*
  2.  *  TwinSock - "Troy's Windows Sockets"
  3.  *
  4.  *  Copyright (C) 1994  Troy Rollo <troy@cbme.unsw.EDU.AU>
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. #include <winsock.h>
  22. #include <stdlib.h>
  23. #include "twinsock.h"
  24. #include "tx.h"
  25.  
  26. HINSTANCE    hinst;
  27.  
  28. extern    RegisterManager(HWND hwnd);
  29. static void SendInitRequest(void);
  30. void    Shutdown(void);
  31. void    OpenPort(void);
  32. extern    int    iPortChanged;
  33.  
  34. #define    READ_MAX    1024
  35. #define    TIMER_ID_SEND        1
  36. #define    TIMER_ID_RECEIVE    2
  37. #define    TIMER_ID_FLUSH        3
  38. #define    TIMER_ID_BREAK        4
  39.  
  40. static    int    idComm;
  41. static    HWND    hwnd;
  42. static    BOOL    bFlushing = FALSE;
  43. static    BOOL    bTerminal = TRUE;
  44.  
  45. #define    SCREEN_COLUMNS    80
  46. #define    SCREEN_ROWS    25
  47. static    char    aachScreen[SCREEN_ROWS][SCREEN_COLUMNS];
  48. static    int    iScrollRow = 0;
  49. static    int    iRow = 0, iColumn = 0;
  50. static    int    cyRow, cxColumn;
  51. #define    ROW_INDEX(x)    ((x + iScrollRow) % SCREEN_ROWS)
  52.  
  53. static    char    const    achProtoInit[] = "@$TSStart$@";
  54. static    int    iInitChar = 0;
  55.  
  56. extern    void PacketReceiveData(void *pvData, int iLen);
  57.  
  58. void    SetTransmitTimeout(void)
  59. {
  60.     KillTimer(hwnd, TIMER_ID_SEND);
  61.     SetTimer(hwnd, TIMER_ID_SEND, 10000, 0);
  62. }
  63.  
  64. void    KillTransmitTimeout(void)
  65. {
  66.     KillTimer(hwnd, TIMER_ID_SEND);
  67. }
  68.  
  69. void    SetReceiveTimeout(void)
  70. {
  71.     KillTimer(hwnd, TIMER_ID_RECEIVE);
  72.     SetTimer(hwnd, TIMER_ID_RECEIVE, 1500, 0);
  73. }
  74.  
  75. void    KillReceiveTimeout(void)
  76. {
  77.     KillTimer(hwnd, TIMER_ID_RECEIVE);
  78. }
  79.  
  80. void    FlushInput(void)
  81. {
  82.     KillTimer(hwnd, TIMER_ID_FLUSH);
  83.     bFlushing = TRUE;
  84.     SetTimer(hwnd, TIMER_ID_FLUSH, 1500, 0);
  85. }
  86.  
  87. static    void
  88. AddChar(char c)
  89. {
  90.     RECT    rcClient;
  91.     RECT    rcRedraw;
  92.  
  93.     if (c == '\r')
  94.     {
  95.         iColumn = 0;
  96.     }
  97.     else if (c == '\b')
  98.     {
  99.         if (iColumn > 0)
  100.             iColumn--;
  101.     }
  102.     else if (c == '\n')
  103.     {
  104.         if (iRow < SCREEN_ROWS - 1)
  105.         {
  106.             iRow++;
  107.         }
  108.         else
  109.         {
  110.             memset(aachScreen[iScrollRow], 0x20, sizeof(aachScreen[iScrollRow]));
  111.             iScrollRow++;
  112.             while (iScrollRow >= SCREEN_ROWS)
  113.                 iScrollRow -= SCREEN_ROWS;
  114.             GetClientRect(hwnd, &rcClient);
  115.             ScrollWindow(hwnd, 0, -cyRow, &rcClient, 0);
  116.             UpdateWindow(hwnd);
  117.         }
  118.     }
  119.     else if (c >= 0x20 && c <= 0x7e)
  120.     {
  121.         aachScreen[ROW_INDEX(iRow)][iColumn] = c;
  122.         rcRedraw.top = iRow * cyRow;
  123.         rcRedraw.left = iColumn * cxColumn;
  124.         rcRedraw.bottom = rcRedraw.top + cyRow;
  125.         rcRedraw.right = rcRedraw.left + cxColumn;
  126.         InvalidateRect(hwnd, &rcRedraw, TRUE);
  127.         if (iColumn < SCREEN_COLUMNS - 1)
  128.             iColumn++;
  129.     }
  130.     if (c == achProtoInit[iInitChar])
  131.     {
  132.         iInitChar++;
  133.         if (iInitChar == strlen(achProtoInit))
  134.         {
  135.             iInitChar = 0;
  136.             bTerminal = 0;
  137.             RegisterManager(hwnd);
  138.             SendInitRequest();
  139.         }
  140.     }
  141.     else
  142.     {
  143.         iInitChar = 0;
  144.     }
  145. }
  146.  
  147. static    void    DoReading(void)
  148. {
  149.     static    char    achBuffer[READ_MAX];
  150.     int    nRead;
  151.     COMSTAT    cs;
  152.     int    i;
  153.  
  154.     do
  155.     {
  156.         nRead = ReadComm(idComm, achBuffer, READ_MAX);
  157.         if (nRead <= 0)
  158.         {
  159.             GetCommError(idComm, &cs);
  160.             nRead = -nRead;
  161.         }
  162.         if (nRead)
  163.         {
  164.             if (bTerminal)
  165.             {
  166.                 HideCaret(hwnd);
  167.                 for (i = 0; i < nRead; i++)
  168.                     AddChar(achBuffer[i]);
  169.                 SetCaretPos(iColumn * cxColumn, iRow * cyRow);
  170.                 ShowCaret(hwnd);
  171.             }
  172.             else if (bFlushing)
  173.             {
  174.                 FlushInput();
  175.             }
  176.             else
  177.             {
  178.                 PacketReceiveData(achBuffer, nRead);
  179.             }
  180.         }
  181.     } while (nRead);
  182. }
  183.  
  184. int    SendData(void *pvData, int iDataLen)
  185. {
  186.     int    nWritten;
  187.     COMSTAT    cs;
  188.     int    iLen;
  189.  
  190.     if (bFlushing)
  191.         return iDataLen; /* Lie */
  192.     iLen = iDataLen;
  193.     do
  194.     {
  195.         nWritten = WriteComm(idComm, pvData, iLen);
  196.         if (nWritten < 0)
  197.         {
  198.             GetCommError(idComm, &cs);
  199.             nWritten = -nWritten;
  200.         }
  201.         iLen -= nWritten;
  202.         pvData = (char *) pvData + nWritten;
  203.     } while (iLen);
  204.     return iDataLen;
  205. }
  206.  
  207. void
  208. PaintScreen(    HWND    hWnd)
  209. {
  210.     int    i, iRow;
  211.     int    iCol;
  212.     TEXTMETRIC tm;
  213.     HFONT    hfontOld;
  214.     HFONT    hfontFixed;
  215.     PAINTSTRUCT ps;
  216.     int    cyHeight;
  217.     int    yPos;
  218.  
  219.     BeginPaint(hWnd, &ps);
  220.     hfontFixed = (HFONT) GetStockObject(SYSTEM_FIXED_FONT);
  221.     hfontOld = (HFONT) SelectObject(ps.hdc, (HGDIOBJ) hfontFixed);
  222.     GetTextMetrics(ps.hdc, &tm);
  223.     cyHeight = tm.tmHeight + tm.tmExternalLeading;
  224.     for (i = 0; i < SCREEN_ROWS; i++)
  225.     {
  226.         iRow = ROW_INDEX(i);
  227.         TextOut(ps.hdc, 0, i * cyRow, aachScreen[iRow], SCREEN_COLUMNS);
  228.     }
  229.     SelectObject(ps.hdc, (HGDIOBJ) hfontOld);
  230.     EndPaint(hWnd, &ps);
  231. }
  232.  
  233. LRESULT    CALLBACK _export
  234. WindowProc(    HWND    hWnd,
  235.         UINT    wMsg,
  236.         WPARAM    wParam,
  237.         LPARAM    lParam)
  238. {
  239.     char    c;
  240.  
  241.     switch(wMsg)
  242.     {
  243.     case WM_COMMAND:
  244.         switch(wParam)
  245.         {
  246.         case 100:
  247.             if (CommsEdit(hWnd))
  248.             {
  249.                 if (iPortChanged)
  250.                 {
  251.                     CloseComm(idComm);
  252.                     OpenPort();
  253.                 }
  254.                 else
  255.                 {
  256.                     InitComm(idComm);
  257.                 }
  258.             }
  259.             break;
  260.  
  261.         case 101:
  262.             if (bTerminal)
  263.             {
  264.                 bTerminal = 0;
  265.                 RegisterManager(hwnd);
  266.                 SendInitRequest();
  267.             }
  268.             break;
  269.  
  270.         case 102:
  271.             if (!bTerminal)
  272.             {
  273.                 Shutdown();
  274.                 SendData("\030\030\030\030\030", 5);
  275.             }
  276.             break;
  277.  
  278.         case 103:
  279.             PostQuitMessage(0);
  280.             break;
  281.  
  282.         case 104:
  283.             if (bTerminal)
  284.             {
  285.                 SetCommBreak(idComm);
  286.                 SetTimer(hwnd, TIMER_ID_BREAK, 1500, 0);
  287.             }
  288.             break;
  289.  
  290.         case 105:
  291.             if (bTerminal)
  292.                 DialNumber(hWnd);
  293.             break;
  294.  
  295.         case 201:
  296.             About(hWnd);
  297.             break;
  298.         }
  299.         break;
  300.  
  301.     case WM_COMMNOTIFY:
  302.         switch(LOWORD(lParam))
  303.         {
  304.         case CN_RECEIVE:
  305.             DoReading();
  306.             break;
  307.         }
  308.         break;
  309.  
  310.     case WM_CHAR:
  311.         if (bTerminal)
  312.         {
  313.             c = wParam;
  314.             SendData(&c, 1);
  315.         }
  316.         break;
  317.  
  318.     case WM_TIMER:
  319.         switch(wParam)
  320.         {
  321.         case TIMER_ID_SEND:
  322.             TimeoutReceived(TIMER_ID_SEND);
  323.             break;
  324.  
  325.         case TIMER_ID_RECEIVE:
  326.             KillTimer(hWnd, TIMER_ID_RECEIVE);
  327.             PacketReceiveData(0, 0);
  328.             break;
  329.  
  330.         case TIMER_ID_FLUSH:
  331.             KillTimer(hWnd, TIMER_ID_FLUSH);
  332.             bFlushing = FALSE;
  333.             break;
  334.  
  335.         case TIMER_ID_BREAK:
  336.             ClearCommBreak(idComm);
  337.             KillTimer(hWnd, TIMER_ID_BREAK);
  338.             break;
  339.         }
  340.         break;
  341.  
  342.     case WM_PAINT:
  343.         PaintScreen(hWnd);
  344.         return 0;
  345.         break;
  346.  
  347.     case WM_SETFOCUS:
  348.         CreateCaret(hWnd, 0, cxColumn, cyRow);
  349.         SetCaretPos(iColumn * cxColumn, iRow * cyRow);
  350.         ShowCaret(hWnd);
  351.         break;
  352.  
  353.     case WM_KILLFOCUS:
  354.         DestroyCaret();
  355.         break;
  356.  
  357.     case WM_USER:
  358.         PacketTransmitData((void *) lParam, wParam, 0);
  359.         DoReading();
  360.         break;
  361.  
  362.     case WM_CLOSE:
  363.         PostQuitMessage(0);
  364.         break;
  365.     }
  366.     return DefWindowProc(hWnd, wMsg, wParam, lParam);
  367. }
  368.  
  369. void
  370. DataReceived(void *pvData, int iLen)
  371. {
  372.     static    struct tx_request *ptxr = 0;
  373.     static    struct tx_request txrHeader;
  374.     static    int    nBytes = 0;
  375.     short    nPktLen;
  376.     enum Functions ft;
  377.     int    nCopy;
  378.  
  379.     while (iLen)
  380.     {
  381.         if (nBytes < 10)
  382.         {
  383.             nCopy = 10 - nBytes;
  384.             if (nCopy > iLen)
  385.                 nCopy = iLen;
  386.             memcpy((char *) &txrHeader + nBytes, pvData, nCopy);
  387.             nBytes += nCopy;
  388.             pvData = (char *) pvData + nCopy;
  389.             iLen -= nCopy;
  390.             if (nBytes == 10)
  391.             {
  392.                 nPktLen = ntohs(txrHeader.nLen);
  393.                 ptxr = (struct tx_request *) malloc(sizeof(struct tx_request) + nPktLen - 1);
  394.                 memcpy(ptxr, &txrHeader, 10);
  395.             }
  396.         }
  397.         if (nBytes >= 10)
  398.         {
  399.             nPktLen = ntohs(txrHeader.nLen);
  400.             ft = (enum Functions) ntohs(txrHeader.iType);
  401.             nCopy = nPktLen - nBytes;
  402.             if (nCopy > iLen)
  403.                 nCopy = iLen;
  404.             if (nCopy)
  405.             {
  406.                 memcpy((char *) ptxr + nBytes, pvData, nCopy);
  407.                 nBytes += nCopy;
  408.                 pvData = (char *) pvData + nCopy;
  409.                 iLen -= nCopy;
  410.             }
  411.             if (nBytes == nPktLen)
  412.             {
  413.                 if (ft == FN_Init)
  414.                 {
  415.                     if (ptxr->id == -1)
  416.                     {
  417.                         SetWindowText(hwnd, "TwinSock - Connected");
  418.                         CloseWindow(hwnd);
  419.                         SetInitialised();
  420.                     }
  421.                 }
  422.                 else
  423.                 {
  424.                     ResponseReceived(ptxr);
  425.                 }
  426.                 free(ptxr);
  427.                 ptxr = 0;
  428.                 nBytes = 0;
  429.             }
  430.         }
  431.     }
  432. }
  433.  
  434. static void
  435. SendInitRequest(void)
  436. {
  437.     struct    tx_request txr;
  438.  
  439.     txr.iType = htons(FN_Init);
  440.     txr.nArgs = 0;
  441.     txr.nLen = htons(10);
  442.     txr.id = -1;
  443.     txr.nError = 0;
  444.     PacketTransmitData(&txr, 10, 0);
  445. }
  446.  
  447. void
  448. Shutdown(void)
  449. {
  450.     bTerminal = 1;
  451.     SetWindowText(hwnd, "TwinSock - No Connection");
  452.     KillTimer(hwnd, TIMER_ID_SEND);
  453.     KillTimer(hwnd, TIMER_ID_RECEIVE);
  454.     KillTimer(hwnd, TIMER_ID_FLUSH);
  455.     ReInitPackets();
  456. }
  457.  
  458. void
  459. OpenPort(void)
  460. {
  461.     char    achProfileEntry[256];
  462.     char    achMsgBuf[512];
  463.     char    *pchError;
  464.  
  465.     do
  466.     {
  467.         iPortChanged = 0;
  468.         GetPrivateProfileString("Config", "Port", "COM1", achProfileEntry, 256, "TWINSOCK.INI");
  469.         idComm = OpenComm(achProfileEntry, 16384, 16384);
  470.         if (idComm < 0)
  471.         {
  472.         switch(idComm)
  473.         {
  474.             case IE_BADID:
  475.                 pchError = "No such device";
  476.                 break;
  477.  
  478.             case IE_BAUDRATE:
  479.                 pchError = "Speed not supported";
  480.                 break;
  481.  
  482.             case IE_BYTESIZE:
  483.                 pchError = "Byte size not supported";
  484.                 break;
  485.  
  486.             case IE_DEFAULT:
  487.                 pchError = "Bad default parameters for port";
  488.                 break;
  489.  
  490.             case IE_HARDWARE:
  491.                 pchError = "Port in use";
  492.                 break;
  493.  
  494.             case IE_MEMORY:
  495.                 pchError = "Out of memory";
  496.                 break;
  497.  
  498.             case IE_NOPEN:
  499.                 pchError = "Device not open";
  500.                 break;
  501.  
  502.             case IE_OPEN:
  503.                 pchError = "Device is already open";
  504.                 break;
  505.  
  506.             default:
  507.                 pchError = "Error Unknown";
  508.                 break;
  509.             }
  510.             sprintf(achMsgBuf,
  511.                 "Unable to open port \"%s\": %s",
  512.                 achProfileEntry,
  513.                 pchError);        
  514.             if (MessageBox(0, achMsgBuf, "TwinSock", MB_OKCANCEL) == IDCANCEL)
  515.                 exit(1);
  516.             if (!CommsEdit(hwnd))
  517.                 exit(1);
  518.         }
  519.     } while (idComm < 0);
  520.  
  521.     InitComm(idComm);
  522.     EnableCommNotification(idComm, hwnd, 1, 0);
  523. }
  524.  
  525. #pragma argsused
  526. int    far    pascal
  527. WinMain(HINSTANCE    hInstance,
  528.     HINSTANCE    hPrec,
  529.     LPSTR        lpCmdLine,
  530.     int        nShow)
  531. {
  532.     WNDCLASS wc;
  533.     MSG    msg;
  534.     char    *pchError;
  535.     TEXTMETRIC    tm;
  536.     HDC    hdc;
  537.     HWND    hwndDesktop;
  538.     HFONT    hfontOld;
  539.     HFONT    hfontFixed;
  540.  
  541.     hinst = hInstance;
  542.     hwndDesktop = GetDesktopWindow();
  543.     hdc = GetDC(hwndDesktop);
  544.     hfontFixed = (HFONT) GetStockObject(SYSTEM_FIXED_FONT);
  545.     hfontOld = (HFONT) SelectObject(hdc, (HGDIOBJ) hfontFixed);
  546.     GetTextMetrics(hdc, &tm);
  547.     SelectObject(hdc, (HGDIOBJ) hfontOld);
  548.     ReleaseDC(hwnd, hdc);
  549.     cxColumn = tm.tmAveCharWidth;
  550.     cyRow = tm.tmHeight + tm.tmExternalLeading;
  551.  
  552.     memset(aachScreen, 0x20, sizeof(aachScreen));
  553.     wc.style = 0;
  554.     wc.lpfnWndProc = WindowProc;
  555.     wc.cbClsExtra = 0;
  556.     wc.cbWndExtra = 0;
  557.     wc.hInstance = hInstance;
  558.     wc.hIcon = LoadIcon(hInstance, "TSICON");
  559.     wc.hCursor = 0;
  560.     wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  561.     wc.lpszMenuName = "TS_MENU";
  562.     wc.lpszClassName = "TwinSock Communications";
  563.     RegisterClass(&wc);
  564.     hwnd = CreateWindow(    "TwinSock Communications",
  565.                 "TwinSock - No Connection",
  566.                 WS_OVERLAPPED |
  567.                  WS_CAPTION |
  568.                  WS_SYSMENU |
  569.                  WS_MINIMIZEBOX |
  570.                  WS_VISIBLE,
  571.                 CW_USEDEFAULT,
  572.                 CW_USEDEFAULT,
  573.                 cxColumn * SCREEN_COLUMNS + 2,
  574.                 cyRow * SCREEN_ROWS + 4 +
  575.                   GetSystemMetrics(SM_CYCAPTION) +
  576.                   GetSystemMetrics(SM_CYMENU),
  577.                 0,
  578.                 0,
  579.                 hInstance,
  580.                 0);
  581.  
  582.     OpenPort();
  583.  
  584.      while (GetMessage(&msg, 0, 0, 0))
  585.     {
  586.         {
  587.             TranslateMessage(&msg);
  588.             DispatchMessage(&msg);
  589.         }
  590.     }
  591. }
  592.